package com.zhuoyue.biz.core.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhuoyue.biz.core.api.domain.GatewayDO;
import com.zhuoyue.biz.core.api.domain.LocalSceneDO;
import com.zhuoyue.biz.core.api.dto.rep.GatewayTimeTaskRepDTO;
import com.zhuoyue.biz.core.api.dto.req.GatewayTimeTaskReqPutDTO;
import com.zhuoyue.biz.core.api.service.GatewayRedisService;
import com.zhuoyue.biz.core.api.service.GatewayService;
import com.zhuoyue.biz.core.api.dto.req.GatewayTimeTaskReqDTO;
import com.zhuoyue.biz.core.command.cmd.common.gateway.TimeTaskParam;
import com.zhuoyue.biz.core.command.cmd.common.scene.SceneControlUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuoyue.biz.core.api.domain.GatewayTimingScene;
import com.zhuoyue.biz.core.api.dao.GatewayTimingSceneMapper;

import static java.lang.Thread.*;

/**
 * 网关时间配置
 *
 * @author wjming
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class GatewayTimingSceneService extends ServiceImpl<GatewayTimingSceneMapper, GatewayTimingScene> {
    private final RedisTemplate redisTemplate;
    private final GatewayRedisService gatewayRedisService;
    private final GatewayService gatewayService;
    private final LocalSceneService sceneService;

    /**
     * 配置网关定时时间
     *
     * @param localSceneDO
     * @param gatewayTimeTaskReqDTO
     * @param gateway
     */
    public void setTimeTask(LocalSceneDO localSceneDO, GatewayTimeTaskReqDTO gatewayTimeTaskReqDTO, GatewayDO gateway) {
        String cmd = "5400${gatewayMac}08${random}${number}${time}${frequency}${cycle}${date}${rule}${dealCmd}";
        String sceneCmd = SceneControlUtil.controlSceneCmd(localSceneDO.getCode(), gateway.getZigbeeMac());
        TimeTaskParam timeTaskParam = new TimeTaskParam();
        timeTaskParam.setDealCmd(sceneCmd);
        timeTaskParam.setGatewayMac(gateway.getZigbeeMac());
        timeTaskParam.setCycle(gatewayTimeTaskReqDTO.getTaskInterval());
        timeTaskParam.setFrequency(gatewayTimeTaskReqDTO.getRepeatTime());
        timeTaskParam.setNumber(gatewayTimeTaskReqDTO.getTaskIndex());
        timeTaskParam.setTime(gatewayTimeTaskReqDTO.getStartTime());
        Map<String, Object> map = JSONObject.parseObject(JSON.toJSONString(timeTaskParam));
        Map<String, Object> req = JSONObject.parseObject(JSON.toJSONString(gatewayTimeTaskReqDTO));
        redisAndCmdSend(map, cmd, gateway.getZigbeeMac(), req, timeTaskParam.getRandom());
    }

    /**
     * 获取网关定时配置信息
     *
     * @param gatewayId
     * @return
     */
    public List<GatewayTimeTaskRepDTO> getByGatewayId(String gatewayId) {
        List<GatewayTimingScene> list = list(Wrappers.<GatewayTimingScene>lambdaQuery()
                .eq(GatewayTimingScene::getGatewayId, gatewayId).orderByAsc(GatewayTimingScene::getCreateTime));
        List<GatewayTimeTaskRepDTO> repDtos = new ArrayList<>(8);
        list.forEach(i -> {
            GatewayTimeTaskRepDTO gatewayTimeTaskRepDTO = new GatewayTimeTaskRepDTO();
            String name = null;
            if (StringUtils.isNotEmpty(i.getSceneId())) {
                name = sceneService.getById(i.getSceneId()).getName();
            }
            gatewayTimeTaskRepDTO.setSceneName(name);
            gatewayTimeTaskRepDTO.setDealId(i.getSceneId());
            BeanUtils.copyProperties(i, gatewayTimeTaskRepDTO);
            repDtos.add(gatewayTimeTaskRepDTO);
        });
        return repDtos;
    }

    /**
     * 修改定时任务场景以及时间
     *
     * @param localSceneDO
     * @param gatewayTimeTaskReqPutDTO
     */
    public void putTimeTask(LocalSceneDO localSceneDO, GatewayTimeTaskReqPutDTO gatewayTimeTaskReqPutDTO) {
        String cmd = "5400${gatewayMac}0D${random}${number}${time}${frequency}${cycle}${date}${rule}${dealCmd}";
        String sceneCmd = SceneControlUtil.controlSceneCmd(localSceneDO.getCode(), localSceneDO.getGatewayMac());
        TimeTaskParam timeTaskParam = new TimeTaskParam();
        timeTaskParam.setDealCmd(sceneCmd);
        timeTaskParam.setGatewayMac(localSceneDO.getGatewayMac());
        timeTaskParam.setCycle(gatewayTimeTaskReqPutDTO.getTaskInterval());
        timeTaskParam.setFrequency(gatewayTimeTaskReqPutDTO.getRepeatTime());
        timeTaskParam.setNumber(gatewayTimeTaskReqPutDTO.getTaskIndex());
        timeTaskParam.setTime(gatewayTimeTaskReqPutDTO.getStartTime());
        Map<String, Object> stringObjectMap = JSONObject.parseObject(JSON.toJSONString(timeTaskParam));
        Map<String, Object> objectMap = JSONObject.parseObject(JSON.toJSONString(gatewayTimeTaskReqPutDTO));

        redisAndCmdSend(stringObjectMap, cmd, localSceneDO.getGatewayMac(), objectMap, timeTaskParam.getRandom());
    }

    /**
     * 删除任务
     *
     * @param id
     * @return
     */
    @Override
    public boolean removeById(Serializable id) {
        String cmd = "5400${gatewayMac}09${random}${number}";
        GatewayTimingScene gatewayTimingScene = getById(id);
        GatewayDO gatewayDO = gatewayService.getById(gatewayTimingScene.getGatewayId());
        TimeTaskParam timeTaskParam = new TimeTaskParam();
        timeTaskParam.setGatewayMac(gatewayDO.getZigbeeMac());
        timeTaskParam.setNumber(gatewayTimingScene.getTaskIndex());
        Map<String, Object> stringObjectMap = JSONObject.parseObject(JSON.toJSONString(timeTaskParam));
        redisAndCmdSend(stringObjectMap, cmd, gatewayDO.getZigbeeMac(), id, timeTaskParam.getRandom());
        return true;
    }

    /**
     * 修改定时任务使能
     *
     * @param gatewayTimeTaskReqPutDTO
     */
    public void putTimeTask(GatewayTimeTaskReqPutDTO gatewayTimeTaskReqPutDTO) {
        String cmd = "5400${gatewayMac}0B${random}${number}${taskEnable}";
        TimeTaskParam timeTaskParam = new TimeTaskParam();
        GatewayDO gatewayDO = gatewayService.getById(gatewayTimeTaskReqPutDTO.getGatewayId());
        timeTaskParam.setGatewayMac(gatewayDO.getZigbeeMac());
        timeTaskParam.setTaskEnable(gatewayTimeTaskReqPutDTO.getTaskEnable());
        timeTaskParam.setNumber(gatewayTimeTaskReqPutDTO.getTaskIndex());
        Map<String, Object> stringObjectMap = JSONObject.parseObject(JSON.toJSONString(timeTaskParam));

        Map<String, Object> objectMap = JSONObject.parseObject(JSON.toJSONString(gatewayTimeTaskReqPutDTO));
        redisAndCmdSend(stringObjectMap, cmd, gatewayDO.getZigbeeMac(), objectMap, timeTaskParam.getRandom());
    }


    /**
     * 清空定时任务
     *
     * @param gatewayId
     */
    public void clearTimed(String gatewayId) {
        String cmd = "5400${gatewayMac}0A${random}";
        TimeTaskParam timeTaskParam = new TimeTaskParam();
        GatewayDO gatewayDO = gatewayService.getById(gatewayId);
        timeTaskParam.setGatewayMac(gatewayDO.getZigbeeMac());
        Map<String, Object> stringObjectMap = JSON.parseObject(JSON.toJSONString(timeTaskParam), new TypeReference<Map<String, Object>>() {
        });
        String replaceCmd = new StrSubstitutor(stringObjectMap).replace(cmd);
        gatewayRedisService.writeDataToGateway(gatewayDO.getZigbeeMac(), replaceCmd);
        //删除该网关下所有定时任务数据
        boolean remove = remove(Wrappers.<GatewayTimingScene>lambdaQuery()
                .eq(GatewayTimingScene::getGatewayId, gatewayId));
    }


    private synchronized void redisAndCmdSend(Map<String, Object> stringObjectMap, String cmd, String gatewayMac, Object dto, String random) {
        String replaceCmd = new StrSubstitutor(stringObjectMap).replace(cmd);
        redisTemplate.opsForValue().set(gatewayMac + "_" + random, dto, 5, TimeUnit.SECONDS);
        gatewayRedisService.writeDataToGateway(gatewayMac, replaceCmd);
    }


    public void removeBySceneId(String sceneId) {
        List<GatewayTimingScene> list = list(Wrappers.<GatewayTimingScene>lambdaQuery()
                .eq(GatewayTimingScene::getSceneId, sceneId));
        list.forEach(l -> {
            boolean b = removeById(l.getId());
            if (b) {
                try {
                    sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}



